package com.zhengbing.tj.controller;

import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import io.swagger.annotations.ApiResponses;
import io.swagger.annotations.ApiResponse;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.zhengbing.tj.common.ApiResult;
import com.zhengbing.tj.common.RedisUtil;
import javax.servlet.http.HttpServletRequest;
import com.zhengbing.tj.entity.User;
import com.zhengbing.tj.service.UserService;
import com.zhengbing.tj.dto.UserRegisterRequest;
import com.zhengbing.tj.service.LoginRecordService;
import com.zhengbing.tj.common.RequestContextUtil;
import com.zhengbing.tj.common.UserContext;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import java.util.List;
import java.util.Map;
import com.zhengbing.tj.utils.JwtUtils;
import java.util.concurrent.TimeUnit;
import cn.hutool.core.util.ReUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.crypto.SecureUtil;
import com.zhengbing.tj.common.PasswordValidator;


/**
 * 用户服务控制器
 * 处理用户相关的REST请求
 *
 * @author zhengbing
 * @date 2025-07-07
 */
@Api(tags = "用户管理", description = "提供用户注册、登录、信息管理等功能")
@RestController
@RequestMapping("/api/users")
public class UserRestController {

  @Autowired
  private JwtUtils jwtUtils;

    @Autowired
    private UserService userService;
    /** Redis操作模板 */
    @Autowired
    private RedisUtil redisUtil;

    @Autowired
    private LoginRecordService loginRecordService;



    /**
     * 用户登出
     * 清除用户token并更新登录状态
     *
     * @return 登出结果
     */
    @ApiOperation(value = "用户登出", notes = "清除用户token并更新登录状态")
    @ApiResponses({
        @ApiResponse(code = 200, message = "登出成功"),
        @ApiResponse(code = 400, message = "未提供token"),
        @ApiResponse(code = 404, message = "用户不存在")
    })
    @PostMapping("/signout")
    public ApiResult<?> signout() {
        // 从请求中获取当前用户
        HttpServletRequest request = RequestContextUtil.getRequest();
        try {
            User user = UserContext.getUserFromRequest(request);
            if (user == null) {
                return ApiResult.error(404, "用户不存在");
            }
            UserContext.setUser(user);
            String token = request.getHeader("Authorization");
            if (StrUtil.isEmpty(token)) {
                return ApiResult.error(400, "未提供token");
            }
            if (!token.startsWith("Bearer ")) {
                return ApiResult.error(400, "token格式错误");
            }
            token = token.substring(7);
            
            // 清理Redis中的用户token
            redisUtil.delete("login:token:" + token);

            // 更新登录记录表的状态
            // 1表示登出状态
            loginRecordService.updateStatusByUserId(user.getId(), 1);
            
            return ApiResult.success("登出成功");
        } catch (IllegalArgumentException e) {
            return ApiResult.error(e.getMessage());
        } finally {
            UserContext.clear();
        }
    }

    /**
     * 获取所有用户
     * 查询系统中的所有用户信息
     *
     * @return 用户列表
     */
    @ApiOperation(value = "获取所有用户", notes = "查询系统中的所有用户信息")
    @ApiResponses({
        @ApiResponse(code = 200, message = "查询成功", response = User.class, responseContainer = "List")
    })
    @GetMapping
    public ApiResult<List<User>> getAllUsers() {
        return ApiResult.success(userService.list());
    }

    /**
     * 根据ID获取用户
     * 根据用户ID查询用户详情
     *
     * @param id 用户ID
     * @return 用户信息
     */
    @ApiOperation(value = "根据ID获取用户", notes = "根据用户ID查询用户详情")
    @ApiResponses({
        @ApiResponse(code = 200, message = "查询成功", response = User.class),
        @ApiResponse(code = 404, message = "用户不存在")
    })
    @GetMapping("/{id}")
    public ApiResult<User> getUserById(@ApiParam(value = "用户ID", required = true, example = "1") @PathVariable Long id) {
        User user = userService.getById(id);
        if (user != null) {
            return ApiResult.success(user);
        } else {
            return ApiResult.error(404, "用户不存在");
        }
    }

    /**
     * 添加用户
     * 创建新用户
     *
     * @param user 用户信息
     * @return 添加结果
     */
    @ApiOperation(value = "添加用户", notes = "创建新用户")
    @ApiResponses({
        @ApiResponse(code = 200, message = "添加成功")
    })
    @PostMapping
    public ApiResult<String> addUser(@ApiParam(value = "用户信息", required = true) @RequestBody User user) {
        userService.save(user);
        return ApiResult.success("添加成功", null);
    }

    /**
     * 更新用户
     * 根据ID更新用户信息
     *
     * @param id 用户ID
     * @param user 用户信息
     * @return 更新结果
     */
    @ApiOperation(value = "更新用户", notes = "根据ID更新用户信息")
    @ApiResponses({
        @ApiResponse(code = 200, message = "更新成功"),
        @ApiResponse(code = 404, message = "用户不存在")
    })
    @PutMapping("/{id}")
    public ApiResult<String> updateUser(@ApiParam(value = "用户ID", required = true, example = "1") @PathVariable Long id, @ApiParam(value = "用户信息", required = true) @RequestBody User user) {
        User existing = userService.getById(id);
        if (existing == null) {
            return ApiResult.error(404, "用户不存在");
        }
        existing.setName(user.getName());
        existing.setEmail(user.getEmail());
        userService.updateById(existing);
        return ApiResult.success("更新成功", null);
    }

    /**
     * 删除用户
     * 根据ID删除用户
     *
     * @param id 用户ID
     * @return 删除结果
     */
    @ApiOperation(value = "删除用户", notes = "根据ID删除用户")
    @ApiResponses({
        @ApiResponse(code = 200, message = "删除成功")
    })
    @DeleteMapping("/{id}")
    public ApiResult<String> deleteUser(@ApiParam(value = "用户ID", required = true, example = "1") @PathVariable Long id) {
        userService.removeById(id);
        return ApiResult.success("删除成功", null);
    }

    /**
     * 用户登录
     * 验证用户身份并返回token
     *
     * @param user 登录信息
     * @return 登录结果和token
     */
    @ApiOperation(value = "用户登录", notes = "验证用户身份并返回token")
    @ApiResponses({
        @ApiResponse(code = 200, message = "登录成功", response = Map.class),
        @ApiResponse(code = 401, message = "用户名或密码错误")
    })
    @PostMapping("/login")
    public ApiResult<?> login(@ApiParam(value = "登录信息", required = true) @RequestBody User user) {
        String name = user.getName();
        String password = user.getPassword();
        User foundUser = userService.getOne(Wrappers.lambdaQuery(User.class).eq(User::getName, name));
        if (foundUser != null && foundUser.getPassword().equals(SecureUtil.md5(password))) {
            String token = jwtUtils.generateToken(name);
            redisUtil.set("login:token:" + foundUser.getId(), token, jwtUtils.getExpirationTime(), TimeUnit.MILLISECONDS);
            // 记录登录信息
            HttpServletRequest request = RequestContextUtil.getRequest();
            String ipAddress = request.getRemoteAddr();
            String deviceInfo = request.getHeader("User-Agent");
            loginRecordService.recordLogin(foundUser.getId(), ipAddress, deviceInfo);
            return ApiResult.success("登录成功", java.util.Collections.singletonMap("token", token));
        } else {
            return ApiResult.error(401, "用户名或密码错误");
        }
    }

    /**
     * 刷新token
     * 使用旧token获取新token
     *
     * @param map 包含旧token的map
     * @return 新token
     */
    @ApiOperation(value = "刷新token", notes = "使用旧token获取新token")
    @ApiResponses({
        @ApiResponse(code = 200, message = "刷新成功", response = Map.class),
        @ApiResponse(code = 401, message = "token无效或已过期")
    })
    @PostMapping("/refresh-token")
    public ApiResult<?> refreshToken(@ApiParam(value = "包含旧token的map", required = true) @RequestBody Map<String, String> map) {
        String oldToken = map.get("token");
        try {
            String username = jwtUtils.getUsernameFromToken(oldToken);
            // 获取用户ID
            User user = userService.getOne(Wrappers.lambdaQuery(User.class).eq(User::getName, username));
            if (user == null) {
                return ApiResult.error(401, "用户不存在");
            }
            // 检查Redis中存储的token是否与传入的oldToken匹配
            String storedToken = redisUtil.get("login:token:" + user.getId());
            if (storedToken == null || !storedToken.equals(oldToken)) {
                return ApiResult.error(401, "token无效或已过期");
            }
            String newToken = jwtUtils.generateToken(username);
            redisUtil.set("login:token:" + user.getId(), newToken, jwtUtils.getExpirationTime(), TimeUnit.MILLISECONDS);
            return ApiResult.success("刷新成功", java.util.Collections.singletonMap("token", newToken));
        } catch (RuntimeException e) {
             return ApiResult.error(401, e.getMessage());
         } catch (Exception e) {
            return ApiResult.error(401, "token无效");
        }
    }

    /**
     * 用户注册
     * 创建新用户账号
     *
     * @param request 注册请求
     * @return 注册结果
     */
    @ApiOperation(value = "用户注册", notes = "创建新用户账号")
    @ApiResponses({
        @ApiResponse(code = 200, message = "注册成功"),
        @ApiResponse(code = 400, message = "参数校验失败")
    })
    @PostMapping("/register")
    public ApiResult<?> register(@ApiParam(value = "注册请求", required = true) @RequestBody UserRegisterRequest request) {
        User user = request.getUser();
        // 邮箱校验
        if (StrUtil.isBlank(user.getEmail())) {
            return ApiResult.error(400, "邮箱不能为空");
        }
        if (!ReUtil.isMatch("^[A-Za-z0-9+_.-]+@[A-Za-z0-9.-]+$", user.getEmail())) {
            return ApiResult.error(400, "邮箱格式不正确");
        }
        // 密码强度校验
        String password = user.getPassword();
        if (!PasswordValidator.validate(password)) {
            return ApiResult.error(400, "密码强度不够，需8位以上且包含大小写字母、数字和特殊字符");
        }
        // 用户名唯一校验
        if (userService.getOne(Wrappers.lambdaQuery(User.class).eq(User::getName, user.getName())) != null) {
            return ApiResult.error(400, "用户名已存在");
        }
        // 密码加密
        user.setPassword(SecureUtil.md5(password));
        userService.save(user);
        return ApiResult.success("注册成功", null);
    }

    /**
     * 删除账号
     * 注销用户账号
     *
     * @param data 包含用户名、密码和邮箱的map
     * @return 注销结果
     */
    @ApiOperation(value = "删除账号", notes = "注销用户账号")
    @ApiResponses({
        @ApiResponse(code = 200, message = "注销成功"),
        @ApiResponse(code = 400, message = "参数不能为空"),
        @ApiResponse(code = 401, message = "邮箱或密码不正确"),
        @ApiResponse(code = 404, message = "用户不存在")
    })
    @PostMapping("/account/delete")
    public ApiResult<?> deleteAccount(@ApiParam(value = "包含用户名、密码和邮箱的map", required = true) @RequestBody Map<String, String> data) {
        String name = data.get("name");
        String password = data.get("password");
        String email = data.get("email");
        if (StrUtil.isBlank(name) || StrUtil.isBlank(password) || StrUtil.isBlank(email)) {
            return ApiResult.error(400, "用户名、密码、邮箱均不能为空");
        }
        User user = userService.getOne(Wrappers.lambdaQuery(User.class).eq(User::getName, name));
        if (user == null) {
            return ApiResult.error(404, "用户不存在");
        }
        if (!user.getEmail().equals(email)) {
            return ApiResult.error(401, "邮箱不正确");
        }
        if (!user.getPassword().equals(SecureUtil.md5(password))) {
            return ApiResult.error(401, "密码不正确");
        }
        userService.removeById(user.getId());
        return ApiResult.success("注销成功", null);
    }
}